/*
 * 	graph.h
 */

/*
 * 	Lista de las supuestas funciones que
 * 	voy a necesitar:
 *
 * 	+ NewGraph
 * 	+ FreeGraph
 * 	+ GraphIsEmpty
 * 	+
 *
 */

typedef struct graphCDT *graphADT;

typedef void* nodeElementT;
typedef void* edgeElementT;

/*
 * 	Definicion de las funciones
 */

/*
 * 	Nodos
 */

typedef int (*nodeCmpFn )( nodeElementT e1, nodeElementT e2 );
typedef int ( *nodeCpyFn ) ( nodeElementT *dst, nodeElementT src );
typedef void ( *nodeFreeFn ) ( nodeElementT node );

/*
 * 	Aristas
 */


typedef int( *edgeCpyFn ) ( edgeElementT *dst, edgeElementT src );
typedef void ( *edgeFreeFn ) ( edgeElementT edge );

/*
 *	Dijkstra
 */

 typedef int( *edgeWeightFn )( edgeElementT e1 );


/*	Funcion que crea un nuevo grafo. Se invoca una unica vez,
** antes de comenzar a aplicarle operaciones al grafo.
** Esta funcion debe recibir un puntero a:
**		Funcion de comparacion de nodos.
**		Funcion de copia de nodos
**
**/

graphADT NewGraph( nodeCmpFn nCmp, nodeCpyFn nCpy, nodeFreeFn nFree, edgeCpyFn eCpy, edgeFreeFn eFree );

/*	Funcion:	GraphIsEmpty
 *	Uso:		if( !GraphIsEmpty ( g ) ) ...
 *	--------------------------------------------------------------------
 *	Descripcion:	Devuelve 1 si el grafo no tiene nodos y 0 en caso
 *					contrario.
 *	---------------------------------------------------------------------
 *	Precondicion :	Grafo creado correctamente
 *	Postcondicion:	---
 */

int GraphIsEmpty( graphADT graph );

/*	Funcion:		NewNode
 *	Uso:			NewNode( graph, nodeElem );
 *	--------------------------------------------------------------------
 *	Descripcion:	Agrega un nodo al grafo. Devuelve 1 si pudo hacerlo,
 *					0 en caso contrario.
 *	---------------------------------------------------------------------
 *	Precondicion :	Grafo creado correctamente
 *	Postcondicion:	Grafo con el nuevo nodo, aislado
 */

int NewNode( graphADT graph, nodeElementT node );

void FreeGraph( graphADT g );

int NewArc( graphADT graph, nodeElementT tail, nodeElementT head, edgeElementT data );

int removeEdge( graphADT graph, nodeElementT tail, nodeElementT head );

int removeNode( graphADT graph, nodeElementT data );

int elementBelongs( graphADT graph, nodeElementT data );

edgeElementT GetOriginalEdge(graphADT graph, nodeElementT tail, nodeElementT head);

int GetEdge(graphADT graph, nodeElementT tail, nodeElementT head, edgeElementT * data);

void removeAllEdges( graphADT graph );

/******************* DIJKSTRA**************************/

/* Se aplica el algoritmo de dijkstra, que almacena cada arista del camino minimo */

int SetBeginDijkstra( graphADT graph, nodeElementT src, nodeElementT tgt );

/* Retorna la siguiente arista del camino minimo, se debe invocar previamente a SetBeginDijkstra 
 * El elemento devuelto es una copia, por lo tanto el usuario es responsable de liberarla */

edgeElementT GetNextDijkstraEdge(graphADT graph);

nodeElementT GetNextNode(graphADT graph);

int GetNextEdge(graphADT graph, nodeElementT src, edgeElementT *edge, nodeElementT *tgt);

int SetNodeIterator(graphADT graph);

int SetEdgeIterator(graphADT graph, nodeElementT src);

void SetWeightFunction(graphADT graph, edgeWeightFn fnW);

nodeElementT* getNodesInfo(graphADT graph, int * n);

